Skip to content

ci: re-lock uv.lock during semantic-release prepare#86

Merged
bartzbeielstein merged 3 commits into
mainfrom
ci/release-relock-uvlock
Jun 4, 2026
Merged

ci: re-lock uv.lock during semantic-release prepare#86
bartzbeielstein merged 3 commits into
mainfrom
ci/release-relock-uvlock

Conversation

@bartzbeielstein
Copy link
Copy Markdown
Contributor

@bartzbeielstein bartzbeielstein commented Jun 4, 2026

Summary

Release-infrastructure fixes that came out of #85's rollout: the uv.lock drift fix, plus the changes needed to make releases work under the new protect-main ruleset, plus a Scorecard TokenPermissions fix.

1. Re-lock uv.lock during semantic-release prepare

semantic-release bumps the version in pyproject.toml but never re-locked, so after every release uv.lock recorded the previous self-version; every uv run then re-locked it, dirtying the tree and tripping the pre-push pytest hook ("files were modified by this hook"). The exec prepareCmd now runs uv lock after the sed bump, and uv.lock ships in the chore(release) commit via the @semantic-release/git assets. Includes the final manual sync (0.12.5 → 0.12.6).

2. Release pushes over SSH via deploy key

The new protect-main ruleset blocks direct pushes to main, and the GitHub Actions app can't be added as a bypass actor on this org (API 422, absent from the UI picker). Instead: release.yml checks out with the DEPLOY_KEY secret, and .releaserc.json pins repositoryUrl to the SSH form so semantic-release pushes the chore(release) commit + tag as the deploy key (covered by the ruleset's DeployKey bypass) instead of constructing an authenticated HTTPS URL from GITHUB_TOKEN and pushing as github-actions[bot] (blocked).

Prerequisites before the next releasable merge (operator actions, not in this PR): create the write deploy key + DEPLOY_KEY secret, and add the "Deploy keys" bypass to ruleset protect-main.

3. Scorecard TokenPermissions fix (alert #118)

quarto-build.yml had no top-level permissions: block (workflow-level read-all is impossible in a called workflow — it may not request more than the caller's job grants). Top-level contents: read is a subset of the callers' contents: write grant, satisfying both the reusable-workflow validation and Scorecard.

Verification

  • actionlint + jq clean; fast suite green via pre-push hook
  • Live test of the SSH release path happens on the next feat:/fix: merge

🤖 Generated with Claude Code

bartzbeielstein and others added 3 commits June 4, 2026 10:34
semantic-release bumped the version in pyproject.toml but never re-locked,
so after every release uv.lock still recorded the previous self-version.
Each subsequent `uv run` then re-locked the file, dirtying the working
tree and failing the pre-push pytest hook with "files were modified by
this hook" despite green tests (one manual one-line sync per release,
see 321226c).

Run `uv lock` in the exec prepareCmd right after the sed version bump and
add uv.lock to the @semantic-release/git assets so the refreshed lockfile
ships inside the chore(release) commit.

Also syncs uv.lock for the 0.12.6 release that predates this fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OpenSSF Scorecard's TokenPermissions check flags workflows with no
top-level permissions block (alert #118). `read-all` is off the table —
a called workflow may not request more than its caller's job grants —
but `contents: read` is a subset of the callers' `contents: write` grant,
so it passes reusable-workflow validation while giving Scorecard the
explicit default it wants. The build-docs job still elevates to
`contents: write` for the gh-pages push.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The new protect-main ruleset blocks direct pushes to main. The GitHub
Actions app cannot be added as a bypass actor on this org (422 from the
API, no suggestion in the UI), so the release pipeline switches to the
deploy-key route instead:

- release.yml checks out with the DEPLOY_KEY secret; actions/checkout
  then configures origin over SSH with that key.
- .releaserc.json pins repositoryUrl to the SSH form so semantic-release
  pushes the chore(release) commit and tag as the deploy key, which the
  ruleset's DeployKey bypass waves through. Without the explicit
  repositoryUrl, semantic-release would construct an authenticated HTTPS
  URL from GITHUB_TOKEN and push as github-actions[bot] — blocked.
- GITHUB_TOKEN continues to serve the GitHub API (release creation).

Requires the DEPLOY_KEY secret (write deploy key) and the DeployKey
bypass on ruleset protect-main to be configured.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bartzbeielstein bartzbeielstein merged commit c668801 into main Jun 4, 2026
5 checks passed
@bartzbeielstein bartzbeielstein deleted the ci/release-relock-uvlock branch June 4, 2026 10:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant